home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 6 / MacMania 6.toast / / Tools&Utilities / EnterAct Stuff / Indent project / Indent Source / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-25  |  23.7 KB  |  1,014 lines  |  [TEXT/MPS ]

  1. /* Copyright (c) 1994, Joseph Arceneaux.  All rights reserved.
  2.  
  3.    Copyright (c) 1992, Free Software Foundation, Inc.  All rights reserved.
  4.  
  5.    Copyright (c) 1985 Sun Microsystems, Inc. Copyright (c) 1980 The Regents
  6.    of the University of California. Copyright (c) 1976 Board of Trustees of
  7.    the University of Illinois. All rights reserved.
  8.  
  9.    Redistribution and use in source and binary forms are permitted
  10.    provided that
  11.    the above copyright notice and this paragraph are duplicated in all such
  12.    forms and that any documentation, advertising materials, and other
  13.    materials related to such distribution and use acknowledge that the
  14.    software was developed by the University of California, Berkeley, the
  15.    University of Illinois, Urbana, and Sun Microsystems, Inc.  The name of
  16.    either University or Sun Microsystems may not be used to endorse or
  17.    promote products derived from this software without specific prior written
  18.    permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  19.    IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
  20.    OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
  21.  
  22. /* This file modified to compile under the Macintosh Metrowerks CodeWarrior
  23.  * programming environment, version 9, as an MPW tool, by Eric Herrmann, erich@slip.net, 8/7/96.
  24.  */
  25.  
  26. #include <string.h>
  27.  
  28. #include "sys.h"
  29. #include "indent.h"
  30. #include <ctype.h>
  31.  
  32. #ifdef __MWERKS__
  33. #include <Files.h>
  34. #include <stat.h>
  35. #else /* __MWERKS__ */
  36. #ifdef VMS
  37. #   include <file.h>
  38. #   include <types.h>
  39. #   include <stat.h>
  40. #else  /* not VMS */
  41.  
  42. /* POSIX says that <fcntl.h> should exist.  Some systems might need to use
  43.    <sys/fcntl.h> or <sys/file.h> instead.  */
  44. #include <fcntl.h>
  45.  
  46. #include <sys/types.h>
  47. #include <sys/stat.h>
  48. #endif /* not VMS */
  49. #endif /* not __MWERKS__ */
  50.  
  51. /* number of levels a label is placed to left of code */
  52. #define LABEL_OFFSET 2
  53.  
  54.  
  55. /* Stuff that needs to be shared with the rest of indent. Documented in
  56.    indent.h.  */
  57. char *in_prog;
  58. char *in_prog_pos;
  59. char *cur_line;
  60. unsigned long in_prog_size;
  61. FILE *output;
  62. char *buf_ptr;
  63. char *buf_end;
  64. int had_eof;
  65. int out_lines;
  66. int com_lines;
  67.  
  68. int suppress_blanklines = 0;
  69. static int comment_open;
  70.  
  71. int paren_target;
  72.  
  73. // Functions defined here:
  74. void sys_error (char *offender);
  75. #ifdef VMS
  76. int vms_read (int file_desc, char *buffer, int nbytes);
  77. #endif /*VMS*/
  78. INLINE int count_columns (int column, char *bp);
  79. INLINE int current_column (void);
  80. void dump_line (void);
  81. INLINE int compute_code_target (void);
  82. INLINE int compute_label_target (void);
  83. struct file_buffer *read_file (char *filename);
  84. struct file_buffer *read_stdin (void);
  85. INLINE void fill_buffer (void);
  86. INLINE int pad_output (int current_column, int target_column);
  87. void diag (int level, char *msg, void *a, void *b);
  88. void writefdef (struct fstate *f, unsigned int nm);
  89. char *chfont (struct fstate *of, struct fstate *nf, char *s);
  90. void parsefont (struct fstate *f, char *s0);
  91. #ifdef DEBUG
  92. void dump_debug_line (void);
  93. #endif
  94.  
  95.  
  96. /* Use `perror' to print the system error message
  97.    caused by OFFENDER, then exit.
  98. Rev for Mac Drag_on Module version, use fprintf */
  99.  
  100. void
  101. sys_error (char *offender)
  102. {
  103.   //int buffer_size;
  104.  // char *errbuf;
  105.   
  106.   fprintf (stderr, "indent syserror: %s", offender);
  107.  
  108.   /* Grab extra space to handle random unix lossage */
  109.  // errbuf = (char *) xmalloc (strlen (offender) + 10);
  110.  
  111.  // sprintf (errbuf, "indent: %s", offender);
  112.  // perror (errbuf);
  113.   exit(1);
  114. }
  115.  
  116. #ifdef VMS
  117. /* Folks say VMS requires its own read routine.  Then again, some folks
  118.    say it doesn't.  Different folks have also sent me conflicting versions
  119.    of this function.  Who's right?
  120.  
  121.    Anyway, this version was sent by MEHRDAD@glum.dev.cf.ac.uk */
  122.  
  123. int
  124. vms_read (int file_desc, char *buffer, int nbytes)
  125. {
  126.     register char *bufp;
  127.     register int nread, nleft;
  128.  
  129.     bufp  = buffer;
  130.     nread = 0;
  131.     nleft = nbytes;
  132.  
  133.     nread = read (file_desc, bufp, nleft);
  134.     while (nread > 0)
  135.       {
  136.         bufp += nread;
  137.         nleft -= nread;
  138.         if (nleft < 0)
  139.       sys_error ("Internal buffering error");
  140.     nread = read (file_desc, bufp, nleft);
  141.       }
  142.  
  143.     return nbytes - nleft;
  144. }
  145. #endif /* VMS */
  146.  
  147. INLINE int
  148. count_columns (int column, char *bp)
  149. {
  150.   while (*bp != '\0')
  151.     {
  152.       switch (*bp++)
  153.     {
  154.     case EOL:
  155.     case 014:        /* form feed */
  156.       column = 1;
  157.       break;
  158.     case TAB:
  159.       column += tabsize - (column - 1) % tabsize;
  160.       break;
  161.     case 010:        /* backspace */
  162.       --column;
  163.       break;
  164.     default:
  165.       ++column;
  166.       break;
  167.     }
  168.     }
  169.  
  170.   return column;
  171. }
  172.  
  173. /* Return the column we are at in the input line. */
  174.  
  175. INLINE int
  176. current_column ()
  177. {
  178.   char *p;
  179.   int column = 1;
  180.  
  181.   if (buf_ptr >= save_com.ptr && buf_ptr <= save_com.end)
  182.     p = save_com.ptr;
  183.   else
  184.     p = cur_line;
  185.  
  186. #if 0
  187.   /* Paranoia -- Turning this on breaks stuff, but I haven't yet
  188.      investigated. */
  189.   if (! (buf_ptr >= cur_line && buf_ptr < in_prog_pos))
  190.     abort();
  191. #endif
  192.  
  193.   column = 1;
  194.   while (p < buf_ptr)
  195.     switch (*p++)
  196.       {
  197.       case EOL:
  198.       case 014:            /* form feed */
  199.     column = 1;
  200.     break;
  201.       case TAB:
  202.     column += tabsize - (column - 1) % tabsize;
  203.     break;
  204.       case '\b':        /* backspace */
  205.     column--;
  206.     break;
  207.       default:
  208.     column++;
  209.     break;
  210.       }
  211.  
  212.   return column;
  213. }
  214.  
  215. void
  216. dump_line ()
  217. {                /* dump_line is the routine that actually
  218.                    effects the printing of the new source. It
  219.                    prints the label section, followed by the
  220.                    code section with the appropriate nesting
  221.                    level, followed by any comments */
  222.   register int cur_col;
  223.   register int target_col = 0;
  224.   static not_first_line;
  225.  
  226.   if (parser_state_tos->procname[0])
  227.     {
  228.       if (troff)
  229.     {
  230.       if (comment_open)
  231.         {
  232.           comment_open = 0;
  233.           fprintf (output, ".*/\n");
  234.         }
  235.       fprintf (output, ".Pr \"%.*s\"\n",
  236.            parser_state_tos->procname_end - parser_state_tos->procname,
  237.            parser_state_tos->procname);
  238.     }
  239.       parser_state_tos->ind_level = 0;
  240.       parser_state_tos->procname = "\0";
  241.     }
  242.  
  243.   /* A blank line */
  244.   if (s_code == e_code && s_lab == e_lab && s_com == e_com)
  245.     {
  246.       /* If we have a formfeed on a blank line, we should just output it,
  247.          rather than treat it as a normal blank line.  */
  248.       if (parser_state_tos->use_ff)
  249.     {
  250.       putc ('\014', output);
  251.       parser_state_tos->use_ff = false;
  252.     }
  253.       else
  254.     {
  255.       if (suppress_blanklines > 0)
  256.         suppress_blanklines--;
  257.       else
  258.         {
  259.           parser_state_tos->bl_line = true;
  260.           n_real_blanklines++;
  261.         }
  262.     }
  263.     }
  264.   else
  265.     {
  266.       suppress_blanklines = 0;
  267.       parser_state_tos->bl_line = false;
  268.       if (prefix_blankline_requested
  269.       && not_first_line
  270.       && n_real_blanklines == 0)
  271.     n_real_blanklines = 1;
  272.       else if (swallow_optional_blanklines && n_real_blanklines > 1)
  273.     n_real_blanklines = 1;
  274.  
  275.       while (--n_real_blanklines >= 0)
  276.     putc (EOL, output);
  277.       n_real_blanklines = 0;
  278.       if (parser_state_tos->ind_level == 0)
  279.     parser_state_tos->ind_stmt = 0;    /* this is a class A kludge. dont do
  280.                        additional statement indentation
  281.                        if we are at bracket level 0 */
  282.  
  283.       if (e_lab != s_lab || e_code != s_code)
  284.     ++code_lines;        /* keep count of lines with code */
  285.  
  286.  
  287.       if (e_lab != s_lab)
  288.     {            /* print lab, if any */
  289.       if (comment_open)
  290.         {
  291.           comment_open = 0;
  292.           fprintf (output, ".*/\n");
  293.         }
  294.       while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == TAB))
  295.         e_lab--;
  296.       cur_col = pad_output (1, compute_label_target ());
  297.       if (s_lab[0] == '#' && (strncmp (s_lab, "#else", 5) == 0
  298.                   || strncmp (s_lab, "#endif", 6) == 0))
  299.         {
  300.           /* Treat #else and #endif as a special case because any text
  301.              after #else or #endif should be converted to a comment.  */
  302.           register char *s = s_lab;
  303.           if (e_lab[-1] == EOL)
  304.         e_lab--;
  305.           do
  306.         putc (*s++, output);
  307.           while (s < e_lab && 'a' <= *s && *s <= 'z');
  308.           while ((*s == ' ' || *s == TAB) && s < e_lab)
  309.         s++;
  310.           if (s < e_lab)
  311.         {
  312.           if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
  313.             fprintf (output, (tabsize > 1 ? "\t%.*s" : "  %.*s"),
  314.                  e_lab - s, s);
  315.           else
  316.             fprintf (output, (tabsize > 1
  317.                       ? "\t/* %.*s */"
  318.                       : "  /* %.*s */"),
  319.                  e_lab - s, s);
  320.         }
  321.         }
  322.       else
  323.         fprintf (output, "%.*s", e_lab - s_lab, s_lab);
  324.       cur_col = count_columns (cur_col, s_lab);
  325.     }
  326.       else
  327.     cur_col = 1;        /* there is no label section */
  328.  
  329.       parser_state_tos->pcase = false;
  330.  
  331.       if (s_code != e_code)
  332.     {            /* print code section, if any */
  333.       register char *p;
  334.       register i;
  335.  
  336.       if (comment_open)
  337.         {
  338.           comment_open = 0;
  339.           fprintf (output, ".*/\n");
  340.         }
  341.  
  342.       /* If a comment begins this line, then indent it to the right
  343.          column for comments, otherwise the line starts with code,
  344.          so indent it for code. */
  345.       if (embedded_comment_on_line == 1)
  346.         target_col = parser_state_tos->com_col;
  347.       else
  348.         target_col = compute_code_target ();
  349.  
  350.       /* If a line ends in an lparen character, the following line should
  351.          not line up with the parenthesis, but should be indented by the
  352.          usual amount.  */
  353.       if (parser_state_tos->last_token == lparen)
  354.         {
  355.           parser_state_tos->paren_indents[parser_state_tos->p_l_follow - 1]
  356.         += ind_size - 1;
  357.         }
  358.  
  359.       for (i = 0; i < parser_state_tos->p_l_follow; i++)
  360.         if (parser_state_tos->paren_indents[i] >= 0)
  361.           parser_state_tos->paren_indents[i]
  362.         = -(parser_state_tos->paren_indents[i] + target_col);
  363.  
  364.       cur_col = pad_output (cur_col, target_col);
  365.       for (p = s_code; p < e_code; p++)
  366.         putc (*p, output);
  367.       cur_col = count_columns (cur_col, s_code);
  368.     }
  369.  
  370.       if (s_com != e_com)
  371.     {
  372.       if (troff)
  373.         {
  374.           int all_here = 0;
  375.           register char *p;
  376.  
  377.           if (e_com[-1] == '/' && e_com[-2] == '*')
  378.         e_com -= 2, all_here++;
  379.           while (e_com > s_com && e_com[-1] == ' ')
  380.         e_com--;
  381.           *e_com = 0;
  382.           p = s_com;
  383.           while (*p == ' ')
  384.         p++;
  385.           if (p[0] == '/' && p[1] == '*')
  386.         p += 2, all_here++;
  387.           else if (p[0] == '*')
  388.         p += p[1] == '/' ? 2 : 1;
  389.           while (*p == ' ')
  390.         p++;
  391.           if (*p == 0)
  392.         goto inhibit_newline;
  393.           if (comment_open < 2 && parser_state_tos->box_com)
  394.         {
  395.           comment_open = 0;
  396.           fprintf (output, ".*/\n");
  397.         }
  398.           if (comment_open == 0)
  399.         {
  400.           if ('a' <= *p && *p <= 'z')
  401.             *p = *p + 'A' - 'a';
  402.           if (e_com - p < 50 && all_here == 2)
  403.             {
  404.               register char *follow = p;
  405.               fprintf (output, "\n.nr C! \\w\1");
  406.               while (follow < e_com)
  407.             {
  408.               switch (*follow)
  409.                 {
  410.                 case EOL:
  411.                   putc (' ', output);
  412.                 case 1:
  413.                   break;
  414.                 case '\\':
  415.                   putc ('\\', output);
  416.                 default:
  417.                   putc (*follow, output);
  418.                 }
  419.               follow++;
  420.             }
  421.               putc (1, output);
  422.             }
  423.           fprintf (output, "\n./* %dp %d %dp\n",
  424.                (int) (parser_state_tos->com_col * 7),
  425.                (int) ((s_code != e_code || s_lab != e_lab)
  426.                   - parser_state_tos->box_com),
  427.                (int) (target_col * 7));
  428.         }
  429.           comment_open = 1 + parser_state_tos->box_com;
  430.           while (*p)
  431.         {
  432.           if (*p == BACKSLASH)
  433.             putc (BACKSLASH, output);
  434.           putc (*p++, output);
  435.         }
  436.         }
  437.       else
  438.         {
  439.           /* Here for comment printing.  This code is new as of
  440.              version 1.8 */
  441.           register target = parser_state_tos->com_col;
  442.           register char *com_st = s_com;
  443.  
  444.           if (cur_col > target)
  445.         {
  446.           putc (EOL, output);
  447.           cur_col = 1;
  448.           ++out_lines;
  449.         }
  450.  
  451.           cur_col = pad_output (cur_col, target);
  452.           fwrite (com_st, e_com - com_st, 1, output);
  453.           cur_col += e_com - com_st;
  454.           com_lines++;
  455.         }
  456.     }
  457.       else if (embedded_comment_on_line)
  458.     com_lines++;
  459.       embedded_comment_on_line = 0;
  460.  
  461.       if (parser_state_tos->use_ff)
  462.     {
  463.       putc ('\014', output);
  464.       parser_state_tos->use_ff = false;
  465.     }
  466.       else
  467.     putc (EOL, output);
  468.  
  469.     inhibit_newline:
  470.       ++out_lines;
  471.       if (parser_state_tos->just_saw_decl == 1
  472.       && blanklines_after_declarations)
  473.     {
  474.       prefix_blankline_requested = 1;
  475.       parser_state_tos->just_saw_decl = 0;
  476.     }
  477.       else
  478.     prefix_blankline_requested = postfix_blankline_requested;
  479.       postfix_blankline_requested = 0;
  480.     }
  481.  
  482.   /* if we are in the middle of a declaration, remember that fact
  483.      for proper comment indentation */
  484.   parser_state_tos->decl_on_line = parser_state_tos->in_decl;
  485.  
  486.   /* next line should be indented if we have not completed this
  487.      stmt and if we are not in the middle of a declaration */
  488.   parser_state_tos->ind_stmt = (parser_state_tos->in_stmt
  489.                 & ~parser_state_tos->in_decl);
  490.  
  491.   parser_state_tos->dumped_decl_indent = 0;
  492.   *(e_lab  = s_lab) = '\0';    /* reset buffers */
  493.   *(e_code = s_code) = '\0';
  494.   *(e_com  = s_com) = '\0';
  495.   parser_state_tos->ind_level = parser_state_tos->i_l_follow;
  496.   parser_state_tos->paren_level = parser_state_tos->p_l_follow;
  497.   if (parser_state_tos->paren_level > 0)
  498.     paren_target
  499.       = -parser_state_tos->paren_indents[parser_state_tos->paren_level - 1];
  500.   else
  501.     paren_target = 0;
  502.   not_first_line = 1;
  503.  
  504.   return;
  505. }
  506.  
  507. /* Return the column in which we should place the code about to be output. */
  508.  
  509. INLINE int
  510. compute_code_target ()
  511. {
  512.   register target_col = parser_state_tos->ind_level + 1;
  513.   register w, t;
  514.  
  515.   if (! parser_state_tos->paren_level)
  516.     {
  517.       if (parser_state_tos->ind_stmt)
  518.     target_col += continuation_indent;
  519.       return target_col;
  520.     }
  521.  
  522.   if (!lineup_to_parens)
  523.     return target_col + (continuation_indent * parser_state_tos->paren_level);
  524.  
  525.   t = paren_target;
  526.   if ((w = count_columns (t, s_code) - max_col) > 0
  527.       && count_columns (target_col, s_code) <= max_col)
  528.     {
  529.       t -= w + 1;
  530.       if (t > target_col)
  531.     target_col = t;
  532.     }
  533.   else
  534.     target_col = t;
  535.  
  536.   return target_col;
  537. }
  538.  
  539. INLINE int
  540. compute_label_target ()
  541. {
  542.   return
  543.   parser_state_tos->pcase ? case_ind + 1
  544.   : *s_lab == '#' ? 1
  545.   : parser_state_tos->ind_level - LABEL_OFFSET + 1;
  546. }
  547.  
  548. /* VMS defines it's own read routine, `vms_read' */
  549. #ifndef SYS_READ
  550. #define SYS_READ read
  551. #endif
  552.  
  553. /* Read file FILENAME into a `fileptr' structure, and return a pointer to
  554.    that structure.
  555.  Rev for Drag_on Module version, return NULL instead of sys_error if trouble.
  556. */
  557.  
  558. static struct file_buffer fileptr;
  559.  
  560. struct file_buffer *
  561. read_file (char *filename)
  562. {
  563. #ifdef __MWERKS__
  564.     struct stat file_stats;
  565.     int namelen = strlen (filename);
  566.     FSSpec    theSpec;
  567.     Str255    name;
  568.     FInfo    fndrInfo;
  569.     short    refNum;
  570.     long    logEOF;
  571.  
  572.     strcpy( (char *) name, filename );
  573.     CtoPstr((Ptr)name );
  574.  
  575.     if ( FSMakeFSSpec( 0, 0, name, &theSpec ) != noErr )
  576.         return NULL;
  577.     if ( FSpOpenDF( &theSpec, fsRdPerm, &refNum ) != noErr )
  578.         return NULL;
  579.     GetEOF( refNum, &logEOF );
  580.     file_stats.st_size = logEOF;
  581.  
  582.     fileptr.size = file_stats.st_size;
  583.     if (fileptr.data != 0)
  584.         fileptr.data = (char *) xrealloc (fileptr.data, file_stats.st_size + 1,
  585.                                             "fileptr.data");
  586.     else
  587.         fileptr.data = (char *) xmalloc (file_stats.st_size + 1);
  588.  
  589.     if ( FSRead( refNum, &logEOF, fileptr.data ) != noErr )
  590.         return NULL;
  591.     FSClose( refNum );
  592.  
  593.     if (fileptr.name != 0)
  594.         fileptr.name = (char *) xrealloc (fileptr.name, namelen + 1, "fileptr.name");
  595.     else
  596.         fileptr.name = (char *) xmalloc (namelen + 1);
  597.     memcpy (fileptr.name, filename, namelen);
  598.     fileptr.name[namelen] = '\0';
  599.  
  600.     fileptr.data[fileptr.size] = '\0';
  601.  
  602.     return &fileptr;
  603. #else
  604.   int fd, size;
  605.   struct stat file_stats;
  606.   int namelen = strlen (filename);
  607.  
  608.   fd = open (filename, O_RDONLY, 0777);
  609.   if (fd < 0)
  610.     sys_error (filename);
  611.  
  612.   if (fstat (fd, &file_stats) < 0)
  613.     sys_error (filename);
  614.  
  615.   if (file_stats.st_size <= 0)
  616.     diag (1, "Warning: Zero-length file %s", filename, NULL);
  617.  
  618.   fileptr.size = file_stats.st_size;
  619.   if (fileptr.data != 0)
  620.     fileptr.data = (char *) xrealloc (fileptr.data, file_stats.st_size + 1,
  621.                                     "fileptr.data2");
  622.   else
  623.     fileptr.data = (char *) xmalloc (file_stats.st_size + 1);
  624.  
  625.   size = SYS_READ (fd, fileptr.data, fileptr.size);
  626.   if (size < 0)
  627.     sys_error (filename);
  628.   if (close (fd) < 0)
  629.     sys_error (filename);
  630.  
  631.   /* Apparently, the DOS stores files using CR-LF for newlines, but
  632.      then the DOS `read' changes them into '\n'.  Thus, the size of the
  633.      file on disc is larger than what is read into memory.  Thanks, Bill. */
  634.   if (size < fileptr.size)
  635.     fileptr.size = size;
  636.  
  637.   if (fileptr.name != 0)
  638.     fileptr.name = (char *) xrealloc (fileptr.name, namelen + 1, "fileptr.name2");
  639.   else
  640.     fileptr.name = (char *) xmalloc (namelen + 1);
  641.   memcpy (fileptr.name, filename, namelen);
  642.   fileptr.name[namelen] = '\0';
  643.  
  644.   fileptr.data[fileptr.size] = '\0';
  645.  
  646.   return &fileptr;
  647. #endif
  648. }
  649.  
  650. /* This should come from stdio.h and be some system-optimal number */
  651. #ifndef BUFSIZ
  652. #define BUFSIZ 1024
  653. #endif
  654.  
  655. /* Suck the standard input into a file_buffer structure, and
  656.    return a pointer to that structure. */
  657.  
  658. struct file_buffer stdinptr;
  659.  
  660. struct file_buffer *
  661. read_stdin ()
  662. {
  663.   size_t size = 15 * BUFSIZ;
  664.   int ch;
  665.   register char *p;
  666.  
  667.   if (stdinptr.data != 0)
  668.     free(stdinptr.data);
  669.  
  670.   stdinptr.data = (char *) xmalloc (size + 1);
  671.   stdinptr.size = 0;
  672.   p = stdinptr.data;
  673.   do
  674.     {
  675.       while (stdinptr.size < size)
  676.     {
  677.       ch = getc (stdin);
  678.       if (ch == EOF)
  679.         break;
  680.  
  681.       *p++ = ch;
  682.       stdinptr.size++;
  683.     }
  684.  
  685.       if (ch != EOF)
  686.     {
  687.       size += (2 * BUFSIZ);
  688.       stdinptr.data = xrealloc (stdinptr.data, size, "stdinptr.data");
  689.       p = stdinptr.data + stdinptr.size;
  690.     }
  691.     }
  692.   while (ch != EOF);
  693.  
  694.   stdinptr.name = "Standard Input";
  695.  
  696.   stdinptr.data[stdinptr.size] = '\0';
  697.  
  698.   return &stdinptr;
  699. }
  700.  
  701. /* Points to the current input buffer */
  702. extern struct file_buffer *current_input;
  703.  
  704. /* Advance `buf_ptr' so that it points to the next line of input.
  705.  
  706.    If the next input line contains an indent control comment turning
  707.    off formatting (a comment, C or C++, beginning with *INDENT-OFF*),
  708.    then simply print out input lines without formatting until we find
  709.    a corresponding comment containing *INDENT-0N* which re-enables
  710.    formatting.
  711.  
  712.    Note that if this is a C comment we do not look for the closing
  713.    delimiter.  Note also that older version of this program also
  714.    skipped lines containing *INDENT** which represented errors
  715.    generated by indent in some previous formatting.  This version does
  716.    not recognize such lines. */
  717.  
  718. INLINE void
  719. fill_buffer ()
  720. {
  721.   register char *p;
  722.   int finished_a_line;
  723.  
  724.   /* indent() may be saving the text between "if (...)" and the following
  725.      statement.  To do so, it uses another buffer (`save_com').  Switch
  726.      back to the previous buffer here. */
  727.   if (bp_save != 0)
  728.     {
  729.       buf_ptr = bp_save;
  730.       buf_end = be_save;
  731.       bp_save = be_save = 0;
  732.  
  733.       /* only return if there is really something in this buffer */
  734.       if (buf_ptr < buf_end)
  735.     return;
  736.     }
  737.  
  738.   if (*in_prog_pos == '\0')
  739.     {
  740.       cur_line = buf_ptr = in_prog_pos;
  741.       had_eof = true;
  742.       return;
  743.     }
  744.  
  745.   /* Here if we know there are chars to read. */
  746.   p = cur_line = in_prog_pos;
  747.   finished_a_line = 0;
  748.   do
  749.     {
  750.       while (*p == ' ' || *p == TAB)
  751.     p++;
  752.       if (*p == '/' && (*(p + 1) == '*' || *(p + 1) == '/'))
  753.     {
  754.       p += 2;
  755.       while (*p == ' ' || *p == TAB)
  756.         p++;
  757.       if (! strncmp (p, "*INDENT-OFF*", 12))
  758.         {
  759.           char *q = cur_line;
  760.           int inhibited = 1;
  761.  
  762.           if (s_com != e_com || s_lab != e_lab || s_code != e_code)
  763.         dump_line ();
  764.           while (q < p)
  765.         putc (*q++, output);
  766.           do
  767.         {
  768.           while (*p != '\0' && *p != EOL)
  769.             putc (*p++, output);
  770.           if (*p == '\0'
  771.               && (p - current_input->data) == current_input->size)
  772.             {
  773.               buf_ptr = buf_end = in_prog_pos = p;
  774.               had_eof = 1;
  775.               return;
  776.             }
  777.  
  778.           if (*p == EOL)
  779.             cur_line = p + 1;
  780.           putc (*p++, output);
  781.           while (*p == ' ' || *p == TAB)
  782.             putc (*p++, output);
  783.           if (*p == '/' && (*(p + 1) == '*' || *(p + 1) == '/'))
  784.             {
  785.               /* We've hit a comment.  See if turns formatting
  786.              back on. */
  787.               putc (*p++, output);
  788.               putc (*p++, output);
  789.               while (*p == ' ' || *p == TAB)
  790.             putc (*p++, output);
  791.               if (! strncmp (p, "*INDENT-ON*", 11))
  792.             {
  793.               do
  794.                 {
  795.                   while (*p != '\0' && *p != EOL)
  796.                 putc (*p++, output);
  797.                   if (*p == '\0' && ((p - current_input->data)
  798.                          == current_input->size))
  799.                 {
  800.                   buf_ptr = buf_end = in_prog_pos = p;
  801.                   had_eof = 1;
  802.                   return;
  803.                 }
  804.                   else
  805.                 {
  806.                   if (*p == EOL)
  807.                     {
  808.                       inhibited = 0;
  809.                       cur_line = p + 1;
  810.                     }
  811.                   putc (*p++, output);
  812.                 }
  813.                 }
  814.               while (inhibited);
  815.             }
  816.             }
  817.         }
  818.           while (inhibited);
  819.         }
  820.     }
  821.  
  822.       while (*p != '\0' && *p != EOL)
  823.     p++;
  824.  
  825.       /* Here for newline -- return unless formatting is off. */
  826.       if (*p == EOL)
  827.     {
  828.       finished_a_line = 1;
  829.       in_prog_pos = p + 1;
  830.     }
  831.       /* Here for embedded NULLs */
  832.       else if ((p - current_input->data) < current_input->size)
  833.     {
  834.       diag (0, "Warning: File %s contains NULL-characters\n",
  835.         current_input->name, NULL);
  836.       p++;
  837.     }
  838.       /* Here for EOF with no terminating newline char. */
  839.       else
  840.     {
  841.       in_prog_pos = p;
  842.       finished_a_line = 1;
  843.     }
  844.     }
  845.   while (!finished_a_line);
  846.  
  847.   buf_ptr = cur_line;
  848.   buf_end = in_prog_pos;
  849. }
  850.  
  851. /* Fill the output line with whitespace up to TARGET_COLUMN, given that
  852.    the line is currently in column CURRENT_COLUMN.  Returns the ending
  853.    column. */
  854.  
  855. INLINE int
  856. pad_output (int current_column, int target_column)
  857. {
  858.   if (troff)
  859.     {
  860.       fprintf (output, "\\h'|%dp'", (int) ((target_column - 1) * 7));
  861.       return 0;
  862.     }
  863.  
  864.   if (current_column >= target_column)
  865.     return current_column;
  866.  
  867.   if (tabsize > 1)
  868.     {
  869.       register int offset;
  870.  
  871.       offset = tabsize - (current_column - 1) % tabsize;
  872.       while (current_column + offset <= target_column)
  873.     {
  874.       putc (TAB, output);
  875.       current_column += offset;
  876.       offset = tabsize;
  877.     }
  878.     }
  879.  
  880.   while (current_column < target_column)
  881.     {
  882.       putc (' ', output);
  883.       current_column++;
  884.     }
  885.  
  886.   return current_column;
  887. }
  888.  
  889. /* Nonzero if we have found an error (not a warning).  */
  890. int found_err;
  891.  
  892. /* Signal an error.  LEVEL is nonzero if it is an error (as opposed to a
  893.    warning.  MSG is a printf-style format string.  Additional arguments are
  894.    additional arguments for printf.  */
  895. /* VARARGS2 */
  896. void diag (int level, char *msg, void *a, void *b)
  897. {
  898.   if (level)
  899.     found_err = 1;
  900.  
  901.   fprintf (stderr, "indent diag:%s:%d: %s: ", in_name, (int) line_no,
  902.        level == 0 ? "Warning" : "Error");
  903.  
  904.   if (msg)
  905.       {
  906.     if (a != NULL && b != NULL)
  907.         fprintf (stderr, msg, a, b);
  908.     else if (a != NULL)
  909.         fprintf (stderr, msg, a);
  910.     else
  911.         fprintf (stderr, msg);
  912.     }
  913.   fprintf (stderr, "\n");
  914. }
  915.  
  916. void writefdef (struct fstate *f, unsigned int nm)
  917. {
  918.   fprintf (output, ".ds f%c %s\n.nr s%c %d\n",
  919.        (int) nm, f->font, nm, (int) f->size);
  920. }
  921.  
  922. /* Write characters starting at S to change the font from OF to NF.  Return a
  923.    pointer to the character after the last character written. For troff mode
  924.    only.  */
  925. char *
  926. chfont (struct fstate *of, struct fstate *nf, char *s)
  927. {
  928.   if (of->font[0] != nf->font[0]
  929.       || of->font[1] != nf->font[1])
  930.     {
  931.       *s++ = '\\';
  932.       *s++ = 'f';
  933.       if (nf->font[1])
  934.     {
  935.       *s++ = '(';
  936.       *s++ = nf->font[0];
  937.       *s++ = nf->font[1];
  938.     }
  939.       else
  940.     *s++ = nf->font[0];
  941.     }
  942.   if (nf->size != of->size)
  943.     {
  944.       *s++ = '\\';
  945.       *s++ = 's';
  946.       if (nf->size < of->size)
  947.     {
  948.       *s++ = '-';
  949.       *s++ = '0' + of->size - nf->size;
  950.     }
  951.       else
  952.     {
  953.       *s++ = '+';
  954.       *s++ = '0' + nf->size - of->size;
  955.     }
  956.     }
  957.   return s;
  958. }
  959.  
  960. void
  961. parsefont (struct fstate *f, char *s0)
  962. {
  963.   register char *s = s0;
  964.   int sizedelta = 0;
  965.   int i;
  966.  
  967.   f->size = 0;
  968.   f->allcaps = 1;
  969.   for (i = 0; i < 4; i++)
  970.     f->font[i] = 0;
  971.  
  972.   while (*s)
  973.     {
  974.       if (isdigit (*s))
  975.     f->size = f->size * 10 + *s - '0';
  976.       else if (isupper (*s))
  977.     if (f->font[0])
  978.       f->font[1] = *s;
  979.     else
  980.       f->font[0] = *s;
  981.       else if (*s == 'c')
  982.     f->allcaps = 1;
  983.       else if (*s == '+')
  984.     sizedelta++;
  985.       else if (*s == '-')
  986.     sizedelta--;
  987.       else
  988.     {
  989.       fprintf (stderr, "indent: bad font specification: %s\n", s0);
  990.       exit(1);
  991.     }
  992.       s++;
  993.     }
  994.   if (f->font[0] == 0)
  995.     f->font[0] = 'R';
  996.   if (bodyf.size == 0)
  997.     bodyf.size = 11;
  998.   if (f->size == 0)
  999.     f->size = bodyf.size + sizedelta;
  1000.   else if (sizedelta > 0)
  1001.     f->size += bodyf.size;
  1002.   else
  1003.     f->size = bodyf.size - f->size;
  1004. }
  1005.  
  1006. #ifdef DEBUG
  1007. void
  1008. dump_debug_line ()
  1009. {
  1010.   fprintf (output, "\n*** Debug output marker line ***\n");
  1011. }
  1012.  
  1013. #endif
  1014.